package com.baifendian.controller;

import com.google.gson.Gson;
import com.baifendian.entity.hosts.HostJson;
import com.baifendian.entity.hosts.Item;
import com.baifendian.entity.screen.AmbProcess;
import com.baifendian.entity.screen.Cpu;
import com.baifendian.entity.screen.Disk;
import com.baifendian.entity.screen.Memory;
import com.baifendian.entity.screen.MonitorScreen;
import com.baifendian.entity.screen.Network;
import java.math.BigDecimal;
import java.util.List;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
//import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * @author peng.guo
 * on 2018/2/22.
 */

@RestController
public class MonitorController {
  //获取hosts
//  private String host_url = "http://172.24.2.187:8080/api/v1/clusters/wind/hosts";

//  private String base_url = "http://172.24.2.187:8080/api/v1/clusters/wind/hosts/bfd-2p189-au-03";
//  private String url = "http://172.24.2.187:8080/api/v1/clusters/wind/hosts/";

  @Autowired
  private RestTemplate restTemplate;

  @Value("${user.userServicePath}")
  private String userServicePath;

  @Value("${ambari.host_url}")
  private String host_url;

  @GetMapping("/check")
  public String findById(){
    MonitorScreen monitorScreenResult = new MonitorScreen();
    Gson gson = new Gson();
    HttpEntity<String> request = getHttpHeaders();

    ResponseEntity<String> hostResponse = restTemplate.exchange(host_url, HttpMethod.GET, request, String.class);
    String hostsBody = hostResponse.getBody();
    HostJson hostJson = gson.fromJson(hostsBody,HostJson.class);
    List<Item> itemList = hostJson.getItems();
    int itemsSize = itemList.size();
    for(Item item : itemList){
      String itemHref = item.getHref();
      ResponseEntity<String> response = restTemplate.exchange(itemHref, HttpMethod.GET, request, String.class);
      String body = response.getBody();
      MonitorScreen monitorScreen = gson.fromJson(body,MonitorScreen.class);
      monitorScreenResult = integrateMonitorScreen(monitorScreen,monitorScreenResult);
    }
    averaging(monitorScreenResult,itemsSize);

//    ResponseEntity<String> response = restTemplate.exchange(base_url, HttpMethod.GET, request, String.class);
//    String body = response.getBody();
//    MonitorScreen monitorScreen = gson.fromJson(body,MonitorScreen.class);
//    System.out.println("id = [" + monitorScreenResult.toString() + "]");
    String monitorScreenJson = gson.toJson(monitorScreenResult);

   return monitorScreenJson;
  }

  /**
   * 求平均值
   * @param monitorScreenResult
   */
  private void averaging(MonitorScreen monitorScreenResult,int itemsSize) {
    // cpu idle
    String cpuIdle = monitorScreenResult.getMetrics().getCpu().getCpu_idle();
    BigDecimal cpuIdleAverage = divide(cpuIdle,itemsSize);
    monitorScreenResult.getMetrics().getCpu().setCpu_idle(cpuIdleAverage.toString());

    // cpu_system
    String cpuSystem = monitorScreenResult.getMetrics().getCpu().getCpu_system();
    BigDecimal cpuSystemAverage = divide(cpuSystem,itemsSize);
    monitorScreenResult.getMetrics().getCpu().setCpu_system(cpuSystemAverage.toString());

    //cpu user
    String cpuUser = monitorScreenResult.getMetrics().getCpu().getCpu_user();
    BigDecimal cpuUserAverage = divide(cpuUser,itemsSize);
    monitorScreenResult.getMetrics().getCpu().setCpu_user(cpuUserAverage.toString());

    // cpu wio
    String cpuWio = monitorScreenResult.getMetrics().getCpu().getCpu_wio();
    BigDecimal cpuWioAverage = divide(cpuWio,itemsSize);
    monitorScreenResult.getMetrics().getCpu().setCpu_user(cpuWioAverage.toString());
  }

  /**
   * 数字相除
   * @param cpuIdle
   */
  private BigDecimal divide(String cpuIdle,int size) {
    BigDecimal cpuIdleDecimal = new BigDecimal(cpuIdle);
    BigDecimal divisor = new BigDecimal(size);
    BigDecimal average = cpuIdleDecimal.divide(divisor,2,BigDecimal.ROUND_DOWN);
    return average;
  }


  /**
   * 组装http头部
   * @return
   */
  private HttpEntity<String> getHttpHeaders() {
    String plainCreds = "admin:admin";
    byte[] plainCredsBytes = plainCreds.getBytes();
    byte[] base64CredsBytes = Base64.encodeBase64(plainCredsBytes);
    String base64Creds = new String(base64CredsBytes);

    HttpHeaders headers = new HttpHeaders();
    headers.add("Authorization", "Basic " + base64Creds);
    headers.add("Accept", MediaType.TEXT_PLAIN_VALUE); // 请求格式会变化
    HttpEntity<String> request = new HttpEntity<String>(headers);
    return request;
  }

  /**
   * 处理 monitorScreen 数据
   * @param monitorScreen
   * @param monitorScreenResult
   */
  private MonitorScreen integrateMonitorScreen(MonitorScreen monitorScreen,MonitorScreen monitorScreenResult){

    // monitorScreenResult 初始化
    if(monitorScreenResult.getMetrics() == null){
        monitorScreenResult = monitorScreen;
        return monitorScreenResult;
    }

    //---------------------------
    // cpu 处理
    //---------------------------
    Cpu cpuResult = monitorScreenResult.getMetrics().getCpu();
    Cpu cpuToAdd = monitorScreen.getMetrics().getCpu();
    //cpu idle
    BigDecimal cpuIdleResult = addElements(cpuResult.getCpu_idle(), cpuToAdd.getCpu_idle());
    monitorScreenResult.getMetrics().getCpu().setCpu_idle(cpuIdleResult.toString());
    //cpu nice
    BigDecimal cpuNiceResult = addElements(cpuResult.getCpu_nice(), cpuToAdd.getCpu_nice());
    monitorScreenResult.getMetrics().getCpu().setCpu_nice(cpuNiceResult.toString());
    //cpu number
    BigDecimal cpuNumResult = addElements(cpuResult.getCpu_num(), cpuToAdd.getCpu_num());
    monitorScreenResult.getMetrics().getCpu().setCpu_num(cpuNumResult.toString());
    //cpu system
    BigDecimal cpuSystemResult = addElements(cpuResult.getCpu_system(), cpuToAdd.getCpu_system());
    monitorScreenResult.getMetrics().getCpu().setCpu_system(cpuSystemResult.toString());
    //cpu_user
    BigDecimal cpuUserResult = addElements(cpuResult.getCpu_user(), cpuToAdd.getCpu_user());
    monitorScreenResult.getMetrics().getCpu().setCpu_user(cpuUserResult.toString());
    //cpu_wio
    BigDecimal cpuWioResult = addElements(cpuResult.getCpu_wio(), cpuToAdd.getCpu_wio());
    monitorScreenResult.getMetrics().getCpu().setCpu_wio(cpuWioResult.toString());

    //---------------------------
    // Disk 处理
    //---------------------------
    Disk diskResult = monitorScreenResult.getMetrics().getDisk();
    Disk diskToAdd = monitorScreen.getMetrics().getDisk();

    double sumFree = diskResult.getDisk_free();
    double additionFree =  diskToAdd.getDisk_free();
    sumFree += additionFree;
    monitorScreenResult.getMetrics().getDisk().setDisk_free(sumFree);

    BigDecimal sumTotalResult = addElements(diskResult.getDisk_total(), diskToAdd.getDisk_total());
    monitorScreenResult.getMetrics().getDisk().setDisk_total(sumTotalResult.toString());

    //---------------------------
    //memory 处理
    //---------------------------
    Memory memoryResult = monitorScreenResult.getMetrics().getMemory();
    Memory memoryToAdd = monitorScreen.getMetrics().getMemory();

    //memory Cached
    BigDecimal memCachedDecimal =  addElements(memoryResult.getMem_cached(),memoryToAdd.getMem_cached());
    monitorScreenResult.getMetrics().getMemory().setMem_cached(memCachedDecimal.toString());

    //memory free
    BigDecimal memFreeDecimal =  addElements(memoryResult.getMem_free(),memoryToAdd.getMem_free());
    monitorScreenResult.getMetrics().getMemory().setMem_free(memFreeDecimal.toString());


    //memory shared
    BigDecimal memSharedDecimal =  addElements(memoryResult.getMem_shared(),memoryToAdd.getMem_shared());
    monitorScreenResult.getMetrics().getMemory().setMem_shared(memSharedDecimal.toString());

    //memory total
    BigDecimal memTotalDecimal =  addElements(memoryResult.getMem_total(),memoryToAdd.getMem_total());
    monitorScreenResult.getMetrics().getMemory().setMem_total(memTotalDecimal.toString());

    //memory swap free
    BigDecimal swapFreeDecimal =  addElements(memoryResult.getSwap_free(),memoryToAdd.getSwap_free());
    monitorScreenResult.getMetrics().getMemory().setSwap_free(swapFreeDecimal.toString());

    //memory swap total
    BigDecimal swapTotalDecimal =  addElements(memoryResult.getSwap_total(),memoryToAdd.getSwap_total());
    monitorScreenResult.getMetrics().getMemory().setSwap_total(swapTotalDecimal.toString());

    //---------------------------
    //network 处理
    //---------------------------
    Network networkResult = monitorScreenResult.getMetrics().getNetwork();
    Network networkToAdd = monitorScreen.getMetrics().getNetwork();

    //bytes in
    BigDecimal bytesInDecimal =  addElements(networkResult.getBytes_in(),networkToAdd.getBytes_in());
    monitorScreenResult.getMetrics().getNetwork().setBytes_in(bytesInDecimal.toString());

    //bytes out
    BigDecimal bytesOutDecimal =  addElements(networkResult.getBytes_out(),networkToAdd.getBytes_out());
    monitorScreenResult.getMetrics().getNetwork().setBytes_out(bytesOutDecimal.toString());

    //---------------------------
    //process 处理
    //---------------------------
    AmbProcess processResult = monitorScreenResult.getMetrics().getProcess();
    AmbProcess processToAdd = monitorScreen.getMetrics().getProcess();
    //proc run
    BigDecimal processRunDecimal =  addElements(processResult.getProc_run(),processToAdd.getProc_run());
    monitorScreenResult.getMetrics().getProcess().setProc_run(processRunDecimal.toString());
    //proc total
    BigDecimal processTotalDecimal =  addElements(processResult.getProc_total(),processToAdd.getProc_total());
    monitorScreenResult.getMetrics().getProcess().setProc_total(processTotalDecimal.toString());

    return monitorScreenResult;
  }

  /**
   * 数字类型的字符串相加
   * @param addend
   * @param augend
   * @return
   */
  private BigDecimal addElements(String addend, String augend){
    BigDecimal addendDecimal = new BigDecimal(addend);
    BigDecimal augendDecimal = new BigDecimal(augend);
    return addendDecimal.add(augendDecimal);
  }

}
